package com.example.opengl_test00;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.util.Log;

public class GLES20SpaceRenderer extends GLES20Renderer implements Renderer {
	
	private FloatBuffer vertexBuf;
	private FloatBuffer colorBuf;
	private float mAngle = 0;
	private Sphere mSphere;
	private Box mBox;
	private Context mContext;
	
	
	
	public GLES20SpaceRenderer(Context context)
	{
		mContext = context;
		
		Vertor3f a = new Vertor3f(10.0f, 0.0f, 0.0f);
		Vertor3f b = new Vertor3f(0.0f, 10.0f, 0.0f);
		Vertor3f c = new Vertor3f(0.0f, 0.0f, 10.0f);
		
		{
			ByteBuffer byteBuf = ByteBuffer.allocateDirect(6 * 3 * 4);
			byteBuf.order(ByteOrder.nativeOrder());
			vertexBuf = byteBuf.asFloatBuffer();
			vertexBuf.put(new float[] { 0.0f, 0.0f, 0.0f });
			vertexBuf.put(a.toArray());
			vertexBuf.put(new float[] { 0.0f, 0.0f, 0.0f });
			vertexBuf.put(b.toArray());
			vertexBuf.put(new float[] { 0.0f, 0.0f, 0.0f });
			vertexBuf.put(c.toArray());
			vertexBuf.position(0);
		}
		
		{
			ByteBuffer byteBuf = ByteBuffer.allocateDirect(6 * 4 * 4);
			byteBuf.order(ByteOrder.nativeOrder());
			colorBuf = byteBuf.asFloatBuffer();
			colorBuf.put(new float[] { 1.0f, 0.0f, 0.0f, 0.0f });
			colorBuf.put(new float[] { 1.0f, 0.0f, 0.0f, 0.0f });
			colorBuf.put(new float[] { 0.0f, 1.0f, 0.0f, 0.0f });
			colorBuf.put(new float[] { 0.0f, 1.0f, 0.0f, 0.0f });
			colorBuf.put(new float[] { 0.0f, 0.0f, 1.0f, 0.0f });
			colorBuf.put(new float[] { 0.0f, 0.0f, 1.0f, 0.0f });
			colorBuf.position(0);
		}
		
		mSphere = new Sphere(10.0f, 16);
		
		mBox = new Box(20.0f, 20.0f, 20.0f);
	}

	@Override
	public void onDrawFrame(GL10 glUnused) {	
		// Ignore the passed-in GL10 interface, and use the GLES20
        // class's static methods instead.
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glUseProgram(mProgram);
        checkGlError("glUseProgram");
        
        
//        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
		
//		final float _23_26 = 23.0f + 26.0f / 60.0f;
		// camera pose
		float eyeX = (float)Math.cos(mAngle) * 40.0f;
		float eyeY = 0.0f;
		float eyeZ = (float)Math.sin(mAngle) * 40.0f;
		float centerX = 0.0f, centerY = 0.0f, centerZ = 0.0f;
		float upX = 0.0f, upY = 1.0f, upZ = 0.0f;
		Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
		
//        long time = SystemClock.uptimeMillis() % 4000L;
//        float angle = 0.090f * ((int) time);
        Matrix.setIdentityM(mMVPMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mMVPMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);

        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
		
//		gl.glMatrixMode(GL10.GL_MODELVIEW);
//		gl.glLoadIdentity();
		
		
		
//		gl.glPushMatrix();
		
//		gl.glRotatef(_23_26,  0.0f, 0.0f, 1.0f);
//		gl.glRotatef(mAngle,  0.0f, 1.0f, 0.0f);
		
//		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuf);
//		gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuf);
//		
//		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//		gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//		
//		gl.glDrawArrays(GL10.GL_LINES, 0, 6);
//		
//		gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
//		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		
//		mSphere.draw(gl);
		
//        if (mProgram != 0)
//        	mBox.draw();
//        else
//        	mBox.draw(GLES20.GL_VERTEX_ATTRIB_ARRAY_POINTER, 0);
		
//		gl.glPopMatrix();
//		
//		gl.glFlush();
		
		mAngle += 0.05f;
	}

	@Override
	public void onSurfaceChanged(GL10 glUnused, int width, int height) {
		Log.d("SpaceRenderer", "onSurfaceChanged");
		GLES20.glViewport(0, 0, width, height);
		
		float ratio = (float)width / (float)height;
		Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1.0f, 1.0f, 1.0f, 100.0f);
	}

	@Override
	public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {		
		Log.d("SpaceRenderer", "onSurfaceCreated");
		// Ignore the passed-in GL10 interface, and use the GLES20
        // class's static methods instead.
        mProgram = createProgram(mVertexShader, mFragmentShader);
        if (mProgram == 0) {
            return;
        }
        
        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
        checkGlError("glGetAttribLocation aPosition");
        if (maPositionHandle == -1) {
            throw new RuntimeException("Could not get attrib location for aPosition");
        }
        
        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
        checkGlError("glGetAttribLocation aTextureCoord");
        if (maTextureHandle == -1) {
            throw new RuntimeException("Could not get attrib location for aTextureCoord");
        }

        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        checkGlError("glGetUniformLocation uMVPMatrix");
        if (muMVPMatrixHandle == -1) {
            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
        }

		/*
		 * lighting
		 */
//		FloatBuffer ambient = FloatBuffer.wrap( new float[] { 0.0f, 0.0f, 0.1f, 1.0f } );
//		FloatBuffer diffuse = FloatBuffer.wrap( new float[] { 0.1f, 0.1f, 0.1f, 1.0f } );
//		FloatBuffer specular = FloatBuffer.wrap( new float[] { 1.0f, 1.0f, 1.0f, 1.0f } );
//		FloatBuffer position0 = FloatBuffer.wrap( new float[] { 15.0f, 15.0f, 20.0f } );
//		FloatBuffer position1 = FloatBuffer.wrap( new float[] {  0.0f, 20.0f,  0.0f } );
		
//		gl.glEnable(GL10.GL_LIGHTING);
		
//		gl.glLightModel(GL10.GL_LIGHT_MODEL_COLOR_CONTROL, GL10.GL_SEPARATE_SPECULAR_COLOR);
		
//		gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, ambient);

//		int light = 0;
		
//		light = GL10.GL_LIGHT0;
//		gl.glEnable(light);
//		gl.glLightfv(light, GL10.GL_POSITION, position0);
//		gl.glLightfv(light, GL10.GL_AMBIENT, ambient);

//		light = GL10.GL_LIGHT1;
//		gl.glEnable(light);
//		gl.glLightfv(light, GL10.GL_POSITION, position0);
// 		gl.glLightfv(light, GL10.GL_DIFFUSE, diffuse);
		
// 		light = GL10.GL_LIGHT2;
//		gl.glEnable(light);
//		gl.glLightfv(light, GL10.GL_POSITION, position0);
// 		gl.glLightfv(light, GL10.GL_SPECULAR, specular);
         
		//mSphere.createTexture(gl, mContext.getResources().openRawResource(R.drawable.earthmap1k));
	}
	
	
	
	private final String mVertexShader =
			"uniform mat4 uMVPMatrix;\n" +
			"attribute vec4 aPosition;\n" +
			"attribute vec2 aTextureCoord;\n" +
			"varying vec2 vTextureCoord;\n" +
			"void main() {\n" +
			"  gl_Position = uMVPMatrix * aPosition;\n" +
			"  vTextureCoord = aTextureCoord;\n" +
			"}\n";
	

	private final String mFragmentShader =
			"precision mediump float;\n" +
			"varying vec2 vTextureCoord;\n" +
			"uniform sampler2D sTexture;\n" +
			"void main() {\n" +
			"  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
			"}\n";
	
	private float[] mProjMatrix = new float[16];
	private float[] mViewMatrix = new float[16];
	private float[] mMVPMatrix = new float[16];

	private int mProgram;
    private int muMVPMatrixHandle;
    private int maPositionHandle;
    private int maTextureHandle;
}
